import os
import time
import datetime
from Common.handle_log import do_log
from Common.handle_path import SCREENSHOT_DIR, SCREENSHOT_QRCODE_DIR
from Common.connect_to_device import *  # 全局驱动 d 重要，勿删！
from functools import cache
import re

class BasePage:

    def __init__(self, device):
        # device传字符串
        self.d = device

    def get_element(self, loc):
        try:
            loc = self.d + loc
            ele = eval(loc)
        except:
            do_log.exception("{} 元素表达式格式错误无法转换".format(loc))
            raise
        else:
            return ele

    # 等待元素存在
    def wait_ele_exists(self, loc, img_desc, timeout=10):
        start = datetime.datetime.now()  # 用datetime模块获取时间
        try:
            ele = self.get_element(loc)
            if not (ele.exists(timeout=timeout)):
                raise Exception
        except:
            do_log.exception("等待 {} 元素 {} 存在失败！".format(img_desc, loc))
            if '.child(textMatches=".+")' in loc:  # 文本获取失败，不用截图
                pass
            else:
                self.save_img(img_desc)
            raise
        else:
            end = datetime.datetime.now()  # 用datetime模块获取当前时间
            do_log.info("等待 {} 元素 {} 存在成功。耗时：{}".format(img_desc, loc, end - start))

    def wait_ele_gone(self, loc, img_desc, timeout=60):
        start = datetime.datetime.now()  # 用datetime模块获取时间
        try:
            ele = self.get_element(loc)
            if not (ele.wait_gone(timeout=timeout)):
                raise Exception
        except:
            do_log.exception("等待 {} 元素 {} 消失失败！".format(img_desc, loc))
            self.save_img(img_desc)
            raise
        else:
            end = datetime.datetime.now()  # 用datetime模块获取当前时间
            do_log.info("等待 {} 元素 {} 消失成功。耗时：{}".format(img_desc, loc, end - start))

    # 判断当前页面元素是否存在
    def judge_ele_exists(self, loc):
        ele = self.get_element(loc)
        if ele.exists:
            do_log.info("{} 元素在当前界面中存在".format(loc))
            return True
        else:
            do_log.info("{} 元素在当前界面中不存在".format(loc))
            return False

    # 判断当前页面所有的元素是否存在
    def judge_all_ele_exists(self, loc_list):
        for loc in loc_list:
            ele = self.get_element(loc)
            if not ele.exists:
                do_log.info("{} 元素在当前界面中不存在".format(loc))
                return False
            do_log.info("{} 元素在当前界面中存在".format(loc))
        return True

    # 先等待当前页面元素
    def _deal_element(self, loc, img_desc, timeout=10):  # 为了加速测试修改为3秒
        self.wait_ele_exists(loc, img_desc, timeout=timeout)
        return self.get_element(loc)

    # 点击元素
    def click_element(self, loc, img_desc, timeout=10, offset=(0.5, 0.5)):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            ele.click(offset=offset)
            do_log.info("点击 {} 元素 {} 成功！".format(img_desc, loc))
        except:
            do_log.exception("点击 {} 元素 {} 失败!".format(img_desc, loc))
            self.save_img(img_desc)
            raise

    # 长按元素
    def long_click_element(self, loc, img_desc, timeout=10, click_time=1):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            ele.long_click(click_time)
            do_log.info("点击 {} 元素 {} 成功！".format(img_desc, loc))
        except:
            do_log.exception("点击 {} 元素 {} 失败!".format(img_desc, loc))
            self.save_img(img_desc)
            raise

    def click_element_geted(self, loc, img_desc, timeout=10):
        ele = loc
        try:
            ele.click()
            do_log.info("点击 {} 元素 {} 成功！".format(img_desc, loc))
        except:
            do_log.exception("点击 {} 元素 {} 失败!".format(img_desc, loc))
            self.save_img(img_desc)
            raise

    # 截图
    def save_img(self, img_description):
        """
        :param img_description: 图片的描述 。格式为 页面名称_功能名
        :return:
        """
        now = time.strftime("%Y-%m-%d %H_%M_%S")
        file_path = "{}_{}.jpg".format(now, img_description)
        img_path = os.path.join(SCREENSHOT_DIR, file_path)
        try:
            eval(self.d).screenshot(img_path)
        except:
            do_log.exception("截图失败！")
        else:
            do_log.info("截图成功，截图存放在：{}".format(img_path))

    def save_img_for_login_qrcode(self):
        """
        :return:
        """
        # now = time.strftime("%Y-%m-%d %H_%M_%S")
        time.sleep(2)
        file_path = "login.jpg"
        img_path = os.path.join(SCREENSHOT_QRCODE_DIR, file_path)
        try:
            eval(self.d).screenshot(img_path)
        except:
            do_log.exception("登录二维码截图失败！")
        else:
            do_log.info("登录二维码截图成功，截图存放在：{}".format(img_path))

        return img_path

    # 录制视频
    def save_video(self, video_time, video_description):
        now = time.strftime("%Y-%m-%d %H_%M_%S")
        file_path = "{}_{}.mp4".format(video_description, now)
        video_path = os.path.join(SCREENSHOT_DIR, file_path)
        try:
            eval(self.d).screenrecord(video_path)
            time.sleep(video_time)
            eval(self.d).screenrecord.stop()
        except:
            do_log.exception("录制视频失败！")
        else:
            do_log.info("录制视频成功，视频存放在：{}".format(video_path))

    # 获取元素的属性值
    def get_element_attribute(self, loc, attr_name, img_desc, timeout=10):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            # info_value = ele.info
            attr_value = ele.info[attr_name]
        except:
            do_log.exception("获取 {} 元素 {} 的属性 {} 失败! ".format(img_desc, loc, attr_name))
            self.save_img(img_desc)
            raise
        else:
            # do_log.info("获取 {} 元素 {} 的属性 {} 值为:{}".format(img_desc, loc, attr_name, info_value))
            do_log.info("获取 {} 元素 {} 的属性 {} 值为:{}".format(img_desc, loc, attr_name, attr_value))
            return attr_value

    # 获取元素的文本值
    def get_text(self, loc, img_desc, timeout=10):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            text = ele.get_text()
        except:
            # 日志
            do_log.exception("获取 {} 元素 {} 的文本失败！".format(img_desc, loc))
            # 截图
            # self.save_img(img_desc)
            raise
        else:
            do_log.info("获取 {} 元素 {} 的文本值为:{}".format(img_desc, loc, text))
            return text

    # 输入文本
    def input_text(self, loc, value, img_desc, timeout=10):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            ele.set_text(value)
            do_log.info("在 {} 元素 {} 上输入文本值: {} 成功！".format(img_desc, loc, value))
        except:
            do_log.exception("在 {} 元素 {} 上输入文本值: {} 失败！".format(img_desc, loc, value))
            self.save_img(img_desc)
            raise




    def get_main_activity(self, package_name):
        # 解析包名的主activity
        try:
            # 执行 dumpsys 获取包的启动 Activity 信息
            result = d_one_device.shell(f"dumpsys package {package_name} | grep -A 1 'MAIN'")

            # 查找包含启动 Activity 的行
            lines = result.splitlines()

            # 如果我们得到了两行输出
            if len(lines) >= 2:
                # 第二行应该包含启动 Activity
                activity_info = lines[1].strip().split()
                if len(activity_info) > 1:
                    return activity_info[1]  # 返回 com.example/.MainActivity 格式的字符串
            return None
        except Exception as e:
            print(f"Error: {e}")
            return None

    def start_IQIYI_app(self):
        try:
            if app_mode=="BeiJing":
                pkgname= "com.qiyi.video.iv"
                do_log.info(pkgname)

                eval(self.d).app_start(f"{pkgname}")

            else:
                if re.match(r"^192\.168\.\d{1,3}\.\d{1,3}:5555$", device_1):
                    activity_info = self.get_main_activity(package_name)
                    d_one_device.shell(f"am start {activity_info}")
                    # d_one_device.shell(f"am start --user 0 --display 1003  {activity_info}")
                else :
                    activity_info = self.get_main_activity(package_name)
                    d_one_device.shell(f"am start {activity_info}")


        except:
            do_log.exception("启动IQYI应用失败")
        else:
            do_log.info("启动IQYI应用成功")

    def close_IQIYI_app(self):
        try:
            if app_mode == "BeiJing":
                pkgname = "com.qiyi.video.iv"
                eval(self.d).app_stop(f"{pkgname}")
            else:
                eval(self.d).app_stop(f"{package_name}")
        except:
            do_log.exception("关闭IQYI应用失败")
        else:
            do_log.info("关闭IQYI应用成功")

    def start_geely_settings(self):
        try:
            eval(self.d).app_start("com.geely.pma.settings")
        except:
            do_log.exception("启动极氪车辆设置失败")
        else:
            do_log.info("启动极氪车辆设置成功")

    def start_bilibili(self):
        try:
            eval(self.d).app_start("com.bilibili.bilithings")
        except:
            do_log.exception("启动哔哩哔哩失败")
        else:
            do_log.info("启动哔哩哔哩成功")

    def wait_for_activity(self, activity, img_desc, timeout=10):
        if eval(self.d).wait_activity(activity, timeout=timeout):
            do_log.info("等待 {} activity 页面加载 成功".format(img_desc))
            return True
        else:
            do_log.exception("等待 {} activity页面加载 失败".format(img_desc))
            return False

    def get_app_current(self):
        current_app = eval(self.d).app_current()
        do_log.info("当前前台运行程序为{}".format(current_app))
        return current_app

    def get_ele_center(self, loc, img_desc, timeout=10):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        try:
            x, y = ele.center()
        except:
            # 日志
            do_log.exception("获取 {} 元素 {} 的中心位置坐标失败！".format(img_desc, loc))
            # 截图
            self.save_img(img_desc)
            raise
        else:
            do_log.info("获取 {} 元素 {} 中心位置坐标为:{},{}".format(img_desc, loc, x, y))
            return x, y


    def click_point(self, x, y, img_desc):
        try:
            eval(self.d).click(x, y)
            do_log.info("点击 {} 坐标点{},{}成功！".format(img_desc, x, y))
        except:
            do_log.exception("点击 {} 坐标点{},{}失败！".format(img_desc, x, y))
            self.save_img(img_desc)
            raise

    def swipe(self, Direction, img_desc):
        try:
            eval(self.d).swipe_ext(Direction)
            do_log.info("向{}方向滑动屏幕成功".format(Direction))
        except:
            do_log.exception("向{}方向滑动屏幕失败".format(Direction))
            self.save_img(img_desc)
            raise


    def open_SCHEME_url(self, url):
        try:
            eval(self.d).open_url(url)
            do_log.info(f"执行SCHEME命令:{url} 成功")
        except:
            do_log.exception(f"执行SCHEME命令:{url} 失败")
            raise



    def timestampTOsecs(self, timestamp):
        # 时间戳转化为秒：{（01:01 =》 61）或(01:01:01 => 3661)}
        strr = timestamp.split(":")
        secs = -1
        if len(strr) == 2:
            secs = int(strr[0]) * 60 + int(strr[1])
        if len(strr) == 3:
            secs = int(strr[0]) * 3600 + int(strr[1]) * 60 + int(strr[2])
        return secs

    @cache
    def get_screen_size(self):
        screen_size = eval(self.d).window_size()
        image = d_one.screenshot()
        image_size=image.size
        if image_size[0]>image_size[1]:
            screen_size_w = max(screen_size)
            screen_size_h = min(screen_size)
            return [screen_size_w, screen_size_h]
        else:
            screen_size_w = min(screen_size)
            screen_size_h = max(screen_size)
            return [screen_size_w, screen_size_h]


    def swip_by_score(self, x1_score, y1_score, x2_score, y2_score, duration, img_desc):
        # do_log.info(f"屏幕尺寸为{screen_size}")
        screen_size_w = screen_size[0]
        screen_size_h = screen_size[1]
        x1 = screen_size_w * x1_score
        x2 = screen_size_w * x2_score
        y1 = screen_size_h * y1_score
        y2 = screen_size_h * y2_score
        try:
            d_one_device.shell(f"input swipe {x1} {y1} {x2} {y2} {duration}")
            do_log.info("从（{},{})向（{},{})滑动成功".format(x1, y1, x2, y2))
        except:
            do_log.exception("从（{},{})向（{},{})滑动失败".format(x1, y1, x2, y2))
            self.save_img(img_desc)
            raise

    def swip_right(self, img_desc):
        try:
            if full_screen==-1:
                self.swip_by_score(0.1, 0.5, 0.4, 0.5, 200, img_desc)
            elif full_screen==1:
                self.swip_by_score(0.6, 0.5, 0.9, 0.5, 200, img_desc)
            else:
                self.swip_by_score(0.2, 0.5, 0.8, 0.5, 200, img_desc)
            do_log.info("向右滑动成功")
        except:
            do_log.exception("向右滑动失败")

    def swipe_by_coordinates(self, x1, y1, x2, y2, duration, img_desc):
        try:
            d_one.swipe(x1, y1, x2, y2, duration)
            do_log.info("从（{},{})向（{},{})滑动成功".format(x1, y1, x2, y2))
        except:
            do_log.exception("从（{},{})向（{},{})滑动失败".format(x1, y1, x2, y2))
            self.save_img(img_desc)
            raise

    def swip_left(self, img_desc):
        try:
            if full_screen==-1:
                self.swip_by_score(0.4, 0.5, 0.1, 0.5, 200, img_desc)
            elif full_screen==1:
                self.swip_by_score(0.9, 0.5, 0.6, 0.5, 200, img_desc)
            else:
                self.swip_by_score(0.8, 0.5, 0.2, 0.5, 200, img_desc)
            do_log.info("向左滑动成功")
        except:
            do_log.exception("向左滑动失败")

    def swip_up(self, img_desc,during=400):
        try:
            if full_screen==-1:
                self.swip_by_score(0.25, 0.7, 0.25, 0.3, during, img_desc)
            elif full_screen==1:
                self.swip_by_score(0.75, 0.7, 0.75, 0.3, during, img_desc)
            else:
                self.swip_by_score(0.5, 0.7, 0.5, 0.3, during, img_desc)
            do_log.info("向上滑动成功")
        except:
            do_log.exception("向上滑动失败")

    def swip_down(self, img_desc,during=150):
        try:
            if full_screen==-1:
                self.swip_by_score(0.25, 0.2, 0.25, 0.8, during, img_desc)
            elif full_screen==1:
                self.swip_by_score(0.75, 0.2, 0.75, 0.8, during, img_desc)
            else:
                self.swip_by_score(0.5, 0.2, 0.5, 0.8, during, img_desc)
                do_log.info("向下滑动成功")
            do_log.info("向下滑动成功")
        except:
            do_log.exception("向下滑动失败")

    def click_point_by_score(self, x, y, img_desc):
        screen_size_w = screen_size[0]
        screen_size_h = screen_size[1]
        x1 = screen_size_w * x
        y1 = screen_size_h * y
        try:
            eval(self.d).click(x1, y1)
            do_log.info("点击 {} 坐标点{},{}成功！".format(img_desc, x1, y1))
        except:
            do_log.exception("点击 {} 坐标点{},{}失败！".format(img_desc, x, y))
            self.save_img(img_desc)
            raise

    def doubleClick_point_by_score(self, x, y, img_desc):
        screen_size_w = screen_size[0]
        screen_size_h = screen_size[1]
        x1 = screen_size_w * x
        y1 = screen_size_h * y
        try:
            eval(self.d).double_click(x1, y1)
            do_log.info("双击 {} 坐标点{},{}成功！".format(img_desc, x, y))
        except:
            do_log.exception("双击 {} 坐标点{},{}失败！".format(img_desc, x, y))
            self.save_img(img_desc)
            raise

    def get_text_loc(self, text):
        text_loc = '(text="#text#")'.replace("#text#", text)
        return text_loc

    def click_text_loc(self, text):
        text_loc = self.get_text_loc(text)
        self.click_element(text_loc, "点击页面上的文字： {}".format(text))

    def judge_textLoc_exists(self, text):
        textLoc = self.get_text_loc(text)
        return self.judge_ele_exists(textLoc)

    def get_xpath_by_id(self, loc):
        id = loc.split('"')[1]
        xpath = "//*[@resource-id='" + id + "']"
        return xpath

    def get_xpath_list_by_id(self, loc):
        id = loc.split('"')[1]
        xpath_list = "//*[@resource-id='" + id + "']/*"
        return xpath_list

    def get_element_BYxpath(self, loc_xpath):
        try:
            d1 = eval(self.d)
            ele = d1.xpath(loc_xpath)
        except:
            do_log.exception("{} 元素表达式格式错误无法转换".format(loc_xpath))
            raise
        else:
            return ele



    def get_element_index(self, loc, img_desc, timeout=10):
        ele = self._deal_element(loc, img_desc, timeout=timeout)
        resourceName = self.get_element_attribute(loc, "resourceName", "获取当前落焦的元素resourceID",
                                                  timeout=timeout)
        all_similar_ele_list = self._deal_element(f'(resourceId="{resourceName}")', img_desc, timeout=timeout)
        ele_index = None
        try:
            for index, value in enumerate(all_similar_ele_list):
                if value.info == ele.info:
                    ele_index = index
                    break
        except:
            do_log.exception("获取 {} 元素 {} 的index值失败! ".format(img_desc, loc))
            self.save_img(img_desc)
            raise
        else:
            do_log.info("获取 {} 元素 {} 的属性 index值为:{}".format(img_desc, loc, ele_index))
            return ele_index




if __name__ == '__main__':
    d1 = BasePage(device="d_one")
    d1.get_app_current()